#include <iostream>
#include <PopupClientUI.hpp>
#include <PopupDefaultLogger.hpp>
#include <PopupOSAL.hpp>
#include <stdlib.h>

using namespace std;
using namespace Popup;

static Client *client;

struct MaquiClient : public ClientUI
{
  LoggerUI *logger;

  MaquiClient(LoggerUI *p_logger) : logger(p_logger) {}

    //!
    //! Event raised to notify client UI when a message comes along with
    //! an attached media file which might take time to be fully received.
    //! When media is completely received, a last event is raised, with
    //! (p_totalSize = p_receivedSize).
    //!
    //! \param[in] p_file         Media file being received
    //! \param[in] p_totalSize    Total size (in bytes) of the media file
    //! \param[in] p_receivedSize Total size (in bytes) already received.
    //!
    virtual void onFileTransferUpdate(__unused__ const FileTransfer *p_tranfer)
    {
        /*AttachmentRecvProgressUpdate(__unused__ AttachmentID p_id,
                                                __unused__ unsigned long senderId,
                                                const std::string & p_attachment,
                                                size_t p_totalSize,
                                                size_t p_receivedSize) {
      printf("\r%s [%03d%%] - %dkB", p_attachment.c_str(),
             int(((float)p_receivedSize/(float)p_totalSize)*100.0), (p_receivedSize/1024));
      if (p_totalSize == p_receivedSize) {
         printf("\n");
      }
    }

    //!
    //! Event raised to notify client UI when a message comes along with
    //! an attached media file which might take time to be fully received.
    //! When media is completely received, a last event is raised, with
    //! (p_totalSize = p_receivedSize).
    //!
    //! \param[in] p_file         Media file being received
    //! \param[in] p_totalSize    Total size (in bytes) of the media file
    //! \param[in] p_receivedSize Total size (in bytes) already received.
    //!
    virtual void onAttachmentSendProgressUpdate(AttachmentID p_id,
                                                const std::string & p_attachment,
                                                size_t p_totalSize,
                                                size_t p_receivedSize) {
      printf("\r%s [%03d%%] - %dkB", p_attachment.c_str(),
             int(((float)p_receivedSize/(float)p_totalSize)*100.0), (p_receivedSize/1024));
      if (p_totalSize == p_receivedSize) {
         printf("\n");
      }
      */
    }
  void onMessageReactionReceived(const UserMessageReaction & p_reaction) {}

    //!
    //! Event raised when a message has been received
    //! and is ready to be displayed
    //!
    virtual void onMessageSent(const UserMessage & p_message) {}

    virtual void onMessageReceived(const UserMessage & p_message) {
      logger->appendLog(POPUP_LOG_TRACE, "Received a message from %d:\n"
                        "%s", p_message.senderID, p_message.text.c_str());
      AttachmentList::const_iterator _it;
      for (_it = p_message.URLs.begin(); _it != p_message.URLs.end(); _it++) {
        logger->appendLog(POPUP_LOG_TRACE, "  URL: %s", _it->c_str());
      }
      for (_it = p_message.files.begin(); _it != p_message.files.end(); _it++) {
        logger->appendLog(POPUP_LOG_TRACE, " file: %s", _it->c_str());
      }
    }

    virtual void onMessageSent(__unused__ unsigned short messageId) {}

    //!
    //! Event raised when connection status has changed
    //!
    //! \param[in] p_isConnected     Tells if client if connected or not
    //!
    virtual void onConnectionUpdate(bool p_connected, User *p_myself) {
      if (p_connected) {
        logger->appendLog(POPUP_LOG_TRACE,
                          "Connection succeeded. My ID is : %d",
                          p_myself->getID());
      }
    }

    //!
    //! Event raised when any user profile has been updated
    //!
    //! \param[in] p_user          Profile of the user which has been updated
    //! \param[in] p_updatedMask   Bit field telling which fields have been updated
    //!
    virtual void onUserUpdate(const User *p_user,
                              unsigned short p_updateMask,
                              bool p_isNewUser) {
      logger->appendLog(POPUP_LOG_TRACE,
                        "[User %d %s]", p_user->getID(),
                        (p_isNewUser? "connected" : "updated"));
      if ((p_updateMask & POPUP_USER_FIELD_NICKNAME) != 0) {
        logger->appendLog(POPUP_LOG_TRACE, "Nickname = %s",
                          p_user->getNickname().c_str());
      }
      if ((p_updateMask & POPUP_USER_FIELD_AVATAR) != 0) {
        logger->appendLog(POPUP_LOG_TRACE, "Avatar   = %s",
                          p_user->getAvatar().c_str());
      }
      if ((p_updateMask & POPUP_USER_FIELD_MODE) != 0) {
        logger->appendLog(POPUP_LOG_TRACE, "Mode     = %d", p_user->getMode());
      }
      if ((p_updateMask & POPUP_USER_FIELD_HEALTH) != 0) {
        logger->appendLog(POPUP_LOG_TRACE, "isAlive  = %d", p_user->isAlive());
      }

      if (p_isNewUser && p_user->getID() == 1) {
        UserMessage message;
        message.text = "bonjour connard!!! Je te prends, je te retourne, et je t'encule";
        message.targets.push_back(p_user->getID());
        message.URLs.push_back("http://www.google.fr");
        message.URLs.push_back("http://stackoverflow.com/questions/704204/what-data-structure-is-behind-fd-set-and-fd-isset-when-working-with-sockets-in-c");
        message.files.push_back("/home/guillou/Photos/IMG_1302.JPG");
        message.files.push_back("/home/guillou/Photos/IMG_1306.JPG");
        message.files.push_back("/media/DOCUMENTS/Mes vidéos/Humour/Laurent Gerra Flingue La Tele.avi");
        (void) client->sendMessage(message);
      }
    }

    //!
    //! Event raised when the PopupClient is about to be destroyed.
    //!
    virtual void onDestroy() {}

  //!
  //! \return The temporary directory which must be used in order
  //! to save the users avatar files.
  //!
  virtual std::string getTemporaryDir() {
    string _path = "/tmp/popup/tmp";
    PopupOSAL::mkdir(_path, 0755);
    return _path;
  }

  //!
  //! \return The temporary directory which must be used in order
  //! to save the users avatar files.
  //!
  virtual std::string getResourceDir() {
    string _path = "/tmp/popup/resources";
    PopupOSAL::mkdir(_path, 0755);
    return _path;
  }
};

static void closeAll(__unused__ int signal) {
  client->disconnect();
  exit(0);
}

int main(__unused__ int argc, char *argv[])
{
  DefaultLogger logger;
  client = Client::newClient(new MaquiClient(&logger), &logger);

  signal(SIGINT,  closeAll);
  signal(SIGTERM, closeAll);
  signal(SIGABRT, closeAll);

  while (true) {
    if (client->connect(argv[1], (unsigned short) atoi(argv[2]),
                    argv[3], argv[4]) != POPUP_CONNECTION_SUCCESS) {
      client->connect(argv[1], (unsigned short) atoi(argv[2]),
                          argv[3], argv[4], true);
    }
    sleep(2);
  }
  logger.appendLog(POPUP_LOG_INFO, "Exited");

  return 0;
}


